package com.dxp.controller;
import com.alibaba.fastjson.JSON;
import com.apache.api.vo.ResultEntity;
import com.apache.api.vo.ResultMsg;
import com.apache.cache.service.impl.LoadCacheFactory;
import com.apache.cache.service.impl.redis.RedisCoreFactory;
import com.apache.client.LogClient;
import com.apache.ius.common.CommonUtils;
import com.apache.ius.controller.BaseAction;
import com.apache.passport.common.DesUtils;
import com.apache.passport.common.PassportHelper;
import com.apache.passport.entity.Token;
import com.apache.portal.common.util.PortalPubFactory;
import com.apache.rpc.common.LoadRpcService;
import com.apache.tools.AesUtil;
import com.apache.tools.RequestTools;
import com.apache.tools.StrUtil;
import com.apache.uct.common.LoginUser;
import com.apache.uct.common.PBOSSOTools;
import com.apache.uct.common.ToolsUtil;
import com.apache.uct.common.entity.User;
import com.dxp.utils.HttpService;
import com.netflix.appinfo.*;
import com.netflix.discovery.DiscoveryManager;
import com.netflix.discovery.EurekaClientConfig;
import com.netflix.discovery.shared.Application;
import com.netflix.discovery.shared.Applications;
import net.sf.json.JSONObject;
import net.sf.json.JsonConfig;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import redis.clients.jedis.Jedis;

import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Controller
@RequestMapping({"/"})
public class IndexAction extends BaseAction {
    /**
    * 欢迎首页
    */
    @RequestMapping(value = "/", method = RequestMethod.GET)
        public String index(HttpServletRequest request) throws ServletException, IOException {
        Map<String, Object> defMap = super.getDefaultDataMap(request);
        if(!defMap.isEmpty() && defMap.containsKey("config")){
            request.setAttribute("config",defMap.get("config"));
        }
        return "/WEB-INF/pages/dxp/admin/index";
    }

    /**
     * 管理端登录（/res/*配置在白名单内）
     */
    @RequestMapping(value = "/res/login", method = RequestMethod.POST)
    @ResponseBody
    public void login(HttpServletRequest request, HttpServletResponse response) throws Exception {
        log.info("request url -->" + request.getRequestURI());
        ResultMsg msg = new ResultMsg("F", "登录失败");
        Map<String, String> params = this.getParameterMap(request);
        Map<String, Object> maps = new HashMap<String, Object>();
        String username = params.get("username");
        String password = params.get("password");

        //验证码判断
        msg = checkRandCode(request, params);
        if (null != msg) {
            gotoErrorPage(request, response, msg.getMsg());
            return;
        }

        //登录账号判断
        if (StrUtil.isNull(username) || StrUtil.isNull(password)) {
            msg = new ResultMsg("F", "用户名或密码不能为空");
            gotoErrorPage(request, response, msg.getMsg());
            return;
        }
        maps.put("userEname", username);
        maps.put("Client-IP", StrUtil.doNull(params.get("Client-IP"), RequestTools.getIp(request)));
        maps.put("userPass", password);
        maps.put("sysEname", ToolsUtil.getInstance().getValueByKey("sysEname"));
        maps.put("addressIP", maps.get("Client-IP"));
        ResultEntity entity = LoadRpcService.service()
                .doServiceClient("ssoService", "outSideSocketLoginService", maps,
                        PortalPubFactory.getInstance().getRpcInfo("sso"));
        //解析sso返回登录结果
        JSONObject resObj = new JSONObject();
        if (entity != null && ("true".equals(entity.getResult())) && !ToolsUtil.isEmpty(entity.getEntity())) {
            if (entity.getEntity() instanceof String) {
                String userMsg = String.valueOf(entity.getMessage());
                log.error("登录提示：" + userMsg);

                if (userMsg.indexOf("用户已停用") > -1) {
                    msg = new ResultMsg("F", "您的账户正在审核，请耐心等待！");
                } else if (userMsg.indexOf("删除") > -1) {
                    msg = new ResultMsg("F", "您的账户已关闭登录操作，请联系管理人员！");
                } else {
                    if ("密码错误".equals(userMsg) || "用户不存在".equals(userMsg)) {
                        msg = new ResultMsg("F", "用户登录信息有误");
                    } else {
                        msg = new ResultMsg("F", userMsg);
                    }
                }
                resObj = JSONObject.fromObject(msg);
            } else {
                //仓储cookie
                Token token = (Token) entity.getEntity();
                Cookie cookie = new Cookie(ToolsUtil.getInstance().getValueByKey("cookieName"),
                        token.getTokenId());
                cookie.setPath("/");
                cookie.setMaxAge(-1);
                Cookie ucsso = new Cookie("_uc.sso",
                        DesUtils.getInstance().decrypt(token.getUserEname()));
                ucsso.setPath("/");
                ucsso.setMaxAge(-1);
                request.getSession().removeAttribute("loginUser");
                request.getSession().removeAttribute("tokenId");

                msg = new ResultMsg("T", "登录成功");

                //剔除loginInfo，解密email，userEname，mobile传明文
                JsonConfig jc = new JsonConfig();
                String config[] = {"loginInfo"};
                jc.setExcludes(config);
                String token_email = token.getEmail();
                String token_mobile = token.getMobile();
                String token_userEname = token.getUserEname();
                token.setEmail(DesUtils.getInstance().decrypt(token_email));
                token.setMobile(DesUtils.getInstance().decrypt(token_mobile));
                token.setUserEname(DesUtils.getInstance().decrypt(token_userEname));
//                msg = new ResultMsg("T", JSONObject.fromObject(token, jc).toString());
                resObj = JSONObject.fromObject(msg, jc);
                //存储session
                if ("T".equals(msg.getFlag())) {
                    JSONObject jb = JSONObject.fromObject(token);
                    Map<String, Object> map = (Map) jb;
                    LoginUser loginUser = PBOSSOTools.getLoginUserFromUserCenter(String.valueOf(map.get("userEname")),
                            String.valueOf(map.get("tokenId")));
                    if (loginUser != null) {
                        jb.put("sysFlag", loginUser.getSysFlag());
                        User user = loginUser.getUser();
                        if (user != null) {
                            Integer userSore = user.getUserScore();
                            if ((!"manager".equals(token.getUserType()) && !"0".equals(token.getUserType())) && 10 != userSore) {
                                msg = new ResultMsg("F", "此账号暂无权限登录");
                                gotoErrorPage(request, response, msg.getMsg());
                                return;
                            }
                            jb.put("auditStatus", StrUtil.doNull(user.getAuditStatus(), ""));
                            jb.put("appId", StrUtil.doNull(user.getAppUid(), ""));
                            jb.put("userScore", userSore);
                        }
                    }
                    resObj.put("loginUser", jb);

                    response.addCookie(cookie);
                    response.addCookie(ucsso);
                    request.getSession().setAttribute("tokenId", token.getTokenId());
                    request.getSession().setAttribute("loginUser", loginUser);
                }
                log.info("[" + username + "]登录成功！");

                //记录日志
                Map<String, Object> logMap = new HashMap<String, Object>();
                logMap.put("logOperationType", "login");
                logMap.put("logClassName", User.class.getName());
                logMap.put("logIp", maps.get("Client-IP"));
                logMap.put("log_userEname", token.getUserEname());
                log.info("登录成功日志：" + logMap);
                LogClient.getInstance().execute(logMap);//添加日志

            }
        }
        log.info("[" + username + "]登录结果：" + msg.toString());
        this.outputJson(resObj.toString(), response, "");
    }

    private final String SERVER_DOWN_KEY="server_down_cache";
    /**
     * 获取注册中心服务列表
     * @return
     */
    @RequestMapping(value = "/serverList", method = RequestMethod.GET)
    @ResponseBody
    public Object eurekaServers(){
        Map<String,Object> data = new HashMap<>();

        DiscoveryManager discoveryClient = DiscoveryManager.getInstance();
        if (null == discoveryClient.getEurekaClient()) {
            data.put("flag", "F");
            data.put("msg", "没有找到注册服务信息");
            return data;
        }
        data.put("flag", "T");
        Applications apps = discoveryClient.getEurekaClient().getApplications();
        List<Map<String,Object>> listInfo = new ArrayList();
        Object obj = LoadCacheFactory.getInstance().getCacheManager(SERVER_DOWN_KEY).getCacheObjectByKey(SERVER_DOWN_KEY);
        Map<String, List<String>> downloadService=null;
        Map<String, List<String>> temp =null;
        boolean ifUpdateCache = false;
        if(null != obj) {//缓存有下线的节点
            downloadService = (Map) obj;
            temp = new HashMap();
            for(Map.Entry<String, List<String>> entry : downloadService.entrySet()){
                temp.put(entry.getKey(),entry.getValue());
            }
        }
        for(Application app : apps.getRegisteredApplications()){
            Map<String,Object> appMap = new HashMap<>();
            appMap.put("serverName",app.getName());
            List<InstanceInfo> list = app.getInstances();
            appMap.put("serverNum",list.size());
            int up = 0;
            int down = 0;
            List ups = new ArrayList();
            List downs = new ArrayList();
            List<String> downUrls = new ArrayList();
            if(null != downloadService && downloadService.containsKey(app.getName())){
                downUrls = downloadService.get(app.getName());
                temp.remove(app.getName());
            }
            for(InstanceInfo info:list){
                Map<String,Object> infoMap = new HashMap<>();
                String homeUrl = info.getHomePageUrl();
                String str = HttpService.sendGetHttp(info.getHomePageUrl()+"info",null);
                infoMap.put("contextPath","");
                if(StrUtil.isNotNull(str)){
                    com.alibaba.fastjson.JSONObject json = JSON.parseObject(str);
                    if(null != json.getJSONObject("app") && json.getJSONObject("app").containsKey("context-path")) {
                        infoMap.put("contextPath", json.getJSONObject("app").getString("context-path"));
                        homeUrl = homeUrl.replaceAll(json.getJSONObject("app").getString("context-path"),"");
                    }
                }
                String address = info.getIPAddr();
                homeUrl = homeUrl.replaceAll(info.getHostName(),address);
                if(info.getStatus().toString().equalsIgnoreCase("UP")){
                    String ckey = homeUrl+infoMap.get("contextPath");
                    if(!downUrls.contains(ckey)){//从下线列表中删除
                        up++;
                        infoMap.put("statusPageUrl",info.getHomePageUrl()+"info");
                        infoMap.put("homePageUrl",homeUrl);
                        ups.add(infoMap);
                        appMap.put("up",ups);
                    }
                } else {
                    down++;
                    infoMap.put("statusPageUrl",homeUrl);
                    infoMap.put("homePageUrl",homeUrl);
                    downs.add(infoMap);
                    appMap.put("down",downs);
                }
            }
            if(null != downloadService && downloadService.containsKey(app.getName())) {
                if(downUrls.isEmpty()){
                    ifUpdateCache = true;
                    downloadService.remove(app.getName());
                } else {
                    for(String key : downUrls){
                        Map<String,Object> infoMap = new HashMap<>();
                        down++;
                        infoMap.put("contextPath","");
                        infoMap.put("statusPageUrl",key);
                        infoMap.put("homePageUrl",key);
                        downs.add(infoMap);
                        appMap.put("down",downs);
                    }
                }
            }
            appMap.put("statusUp",up);
            appMap.put("statusDown",down);
            listInfo.add(appMap);
        }
        if(!StrUtil.isEmpty(temp) && !temp.isEmpty()) {
            for (Map.Entry<String, List<String>> entry : temp.entrySet()) {
                Map<String,Object> appMap = new HashMap<>();
                appMap.put("serverName",entry.getKey());
                List<String> downUrls = entry.getValue();
                appMap.put("serverNum",downUrls.size());
                List details = new ArrayList();
                for(String val : downUrls) {
                    Map<String, Object> infoMap = new HashMap<>();
                    infoMap.put("contextPath", "");
                    infoMap.put("statusPageUrl", val);
                    infoMap.put("homePageUrl", val);
                    details.add(infoMap);
                    appMap.put("down", details);
                }
                appMap.put("statusUp","0");
                appMap.put("statusDown",downUrls.size());
                listInfo.add(appMap);
            }
        }
        if(ifUpdateCache){//是否要更新缓存
            if (downloadService.isEmpty()) {//下线服务已全部上线
                LoadCacheFactory.getInstance().getCacheManager(SERVER_DOWN_KEY).removeCacheObject(SERVER_DOWN_KEY);
            } else {
                LoadCacheFactory.getInstance().getCacheManager(SERVER_DOWN_KEY).createCacheObject(SERVER_DOWN_KEY, downloadService,300);
            }
        }
        data.put("total",listInfo.size());
        data.put("rows",listInfo);
        return data;
    }

    @ResponseBody
    @RequestMapping(value = "/toLine", method = RequestMethod.POST)
    public ResultMsg serverManager(HttpServletRequest request,HttpServletResponse response) throws Exception{
        Map<String, String> params = this.getParameterMap(request);
        String url = AesUtil.aesDecrypt(params.get("url")) ;
        String type = params.get("type");
        String serverId = params.get("serverId");
        log.info("url:"+url);
        log.info("type:"+type);
        log.info("serverId:"+serverId);
        String toUrl ="";
        if("on".equals(type)){
            toUrl = url+ "online";
        } else {
            toUrl = url+ "offline?sign=Constant.OFFLINE_KEY";
        }
        Map<String,String> heads = new HashMap<>();
        heads.put("zuultokenid", PassportHelper.getInstance().getCurrCookie(request));
        heads.put("zuulucsso",PassportHelper.getInstance().getCurrCookie(request, "_uc.sso"));
        String msg = HttpService.sendGetHttp(toUrl,heads);
        Object obj = LoadCacheFactory.getInstance().getCacheManager(SERVER_DOWN_KEY).getCacheObjectByKey(SERVER_DOWN_KEY);
        if("off".equals(type) && "下线成功".equals(msg)){
            Map<String,List> map = null;
            List<String> urls = new ArrayList();
            if(obj ==null){
                map = new HashMap<>();
                urls.add(url);
                map.put(serverId,urls);
            } else {
                map = (Map)obj;
                if(map.containsKey(serverId)){
                    urls = map.get(serverId);
                    urls.add(url);
                    map.put(serverId,urls);
                } else {
                    urls.add(url);
                    map.put(serverId,urls);
                }
            }
            LoadCacheFactory.getInstance().getCacheManager(SERVER_DOWN_KEY).createCacheObject(SERVER_DOWN_KEY,map,300);
        } else {
            if(obj != null){
                Map<String,List> map = (Map)obj;
                List<String> urls = map.get(serverId);
                if(!StrUtil.isEmpty(urls)) {
                    urls.remove(url);// = urls.replaceAll(url, "").replace(";;", ";");
                    if (urls.isEmpty()){//";".equals(urls) || StrUtil.isNull(urls)) {
                        map.remove(serverId);
                    } else {
                        map.put(serverId, urls);
                    }
                    if (map.isEmpty()) {
                        LoadCacheFactory.getInstance().getCacheManager(SERVER_DOWN_KEY).removeCacheObject(SERVER_DOWN_KEY);
                    } else {
                        LoadCacheFactory.getInstance().getCacheManager(SERVER_DOWN_KEY).createCacheObject(SERVER_DOWN_KEY, map,300);
                    }
                }
            }
        }
        if(StrUtil.isNull(msg)){
            msg = "操作失败";
        }
        ResultMsg resultMsg = new ResultMsg("T", msg);
        return resultMsg;
    }

    /**
     * description:  验证验证码
     */
    private ResultMsg checkRandCode(HttpServletRequest request, Map<String, String> params) {
        String if_randCode = StrUtil.doNull(CommonUtils.getConfigVal("if_randCode"), "T");
        if ("F".equals(if_randCode)) {
            return null;
        }
        ResultMsg msg = null;
        String session_randCode = String.valueOf(request.getSession().getAttribute("randCode"));
        if (ToolsUtil.isNull(session_randCode))
            return null;
        if ((StrUtil.isNull(params.get("rand")))) {
            msg = new ResultMsg("F", "验证码不能为空");
            return msg;
        }
        if (!params.get("rand").equals(session_randCode)) {
            msg = new ResultMsg("F", "验证码错误");
            return msg;
        }
        return msg;
    }

    /**
     * 下线本项目
     */
    @RequestMapping(value = "/offline", method = RequestMethod.GET)
    @ResponseBody
    public String offLine(HttpServletRequest request) {
        String sign = request.getParameter("sign");
        if("Constant.OFFLINE_KEY".equals(sign)){
            //EurekaClientConfig ecc = DiscoveryManager.getInstance().getEurekaClientConfig();
           // EurekaInstanceConfig eic = DiscoveryManager.getInstance().getEurekaInstanceConfig();
           // ApplicationInfoManager.getInstance().setInstanceStatus(InstanceInfo.InstanceStatus.DOWN);
           // DiscoveryManager.getInstance().initComponent(eic, ecc);
            DiscoveryManager.getInstance().shutdownComponent();
            return "下线成功";
        }
        return "签名不正确";
    }

    /**
     * 项目手动上线
     */
    @RequestMapping(value = "/online", method = RequestMethod.GET)
    @ResponseBody
    public String online(){
        if(!InstanceInfo.InstanceStatus.UP.equals(ApplicationInfoManager.getInstance().getInfo().getStatus())) {
            EurekaClientConfig ecc = DiscoveryManager.getInstance().getEurekaClientConfig();
            EurekaInstanceConfig eic = DiscoveryManager.getInstance().getEurekaInstanceConfig();
            ApplicationInfoManager.getInstance().setInstanceStatus(InstanceInfo.InstanceStatus.UP);
            DiscoveryManager.getInstance().initComponent(eic, ecc);
            return "上线成功";
        } else {
            return "服务处于发布状态不需上线操作";
        }
    }

}


